﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace SpiritEngine.Components2D
{
    public class C2D_Sprite : AComponent
    {
        // MEMBER VARIABLES
        // ------------------------------------------------------------------------------------------------------------------------

        protected Texture2D m_t2dSpriteTexture;

        protected string m_strFilename;

        protected Vector2 m_v2Position = Vector2.Zero;

        protected Vector2 m_v2Origin = Vector2.Zero;
        protected float m_fRotation = 0;
        protected Rectangle m_rectSource;
        protected float m_fScale = 1;
        protected Color m_Color = Color.White;
        protected SpriteEffects m_seEffects = SpriteEffects.None;


        // CONSTRUCTORS
        // ------------------------------------------------------------------------------------------------------------------------

        public C2D_Sprite()
        {

        } // end C2D_Sprite::C2D_Sprite()

        public C2D_Sprite(float x, float y, float rotation, string strFilename)
        {
            m_v2Position = new Vector2(x, y);
            m_strFilename = strFilename;
            m_v2Origin = Vector2.Zero;
            m_fRotation = rotation;
            m_rectSource = new Rectangle();
            m_fScale = 1;
            m_Color = Color.White;
            m_seEffects = SpriteEffects.None;

        } // end C2D_Sprite::C2D_Sprite(float, float, float, string)


        // PRIVATE/PROTECTED METHODS
        // ------------------------------------------------------------------------------------------------------------------------

        protected override void Load()
        {
            if (m_t2dSpriteTexture == null)
            {
                m_t2dSpriteTexture = new Texture2D(ParentGameScreen.Engine.GraphicsDevice, m_rectSource.Width, m_rectSource.Height);
            }

            m_t2dSpriteTexture = ParentGameScreen.Engine.Content.Load<Texture2D>(m_strFilename);

            // Don't set the SourceRectangle property now if it has already been set
            if (m_rectSource == new Rectangle())
                m_rectSource = new Rectangle(0, 0, m_t2dSpriteTexture.Width, m_t2dSpriteTexture.Height);

            m_v2Origin = new Vector2(m_rectSource.Width / 2f,
                                     m_rectSource.Height / 2f);

        } // end void C2D_Sprite::Load()

        protected virtual void ResetRenderStates()
        {
            ParentGameScreen.Engine.GraphicsDevice.RenderState.DepthBufferEnable = true;
            ParentGameScreen.Engine.GraphicsDevice.RenderState.AlphaBlendEnable = false;
            ParentGameScreen.Engine.GraphicsDevice.RenderState.AlphaTestEnable = false;

        } // end C2D_Sprite::ResetRenderStates()


        // METHODS
        // ------------------------------------------------------------------------------------------------------------------------

        // This function centeres the sprite on the screen.
        // It will not work if this C2D_Sprite object has not been added into a GameScreen.
        public void Center()
        {
            // Check if this C2D_Sprite object is in a GameScreen.  If it is not, then simply exit this
            // function since we can't center the sprite if it's not in a GameScreen yet.
            if (this.ParentGameScreen == null)
                return;

            // Center this sprite on the screen.
            m_v2Position = new Vector2( (ParentGameScreen.Engine.GraphicsDevice.Viewport.Width / 2) - (m_rectSource.Width / 2),
                                        (ParentGameScreen.Engine.GraphicsDevice.Viewport.Height / 2) - (m_rectSource.Height / 2) );
        } // end void C2D_Sprite::Center();
        
        public override void Draw()
        {
            ParentGameScreen.Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                                            SpriteSortMode.Deferred,
                                            SaveStateMode.None);

            ParentGameScreen.Engine.SpriteBatch.Draw(m_t2dSpriteTexture, 
                                           m_v2Position, 
                                           m_rectSource, 
                                           m_Color,
                                           m_fRotation, 
                                           m_v2Origin, 
                                           m_fScale, 
                                           m_seEffects, 0);

            ParentGameScreen.Engine.SpriteBatch.End();

            // Set back certain render states that are changed by the SpriteBatch
            // so they don't interfere with any 3D rendering we may do.
            ResetRenderStates();
                                            
        } // end void C2D_Sprite::Draw()

        public void Draw(GameScreen gs)
        {
            gs.Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                                            SpriteSortMode.Deferred,
                                            SaveStateMode.None);

            gs.Engine.SpriteBatch.Draw(m_t2dSpriteTexture,
                                           m_v2Position,
                                           m_rectSource,
                                           m_Color,
                                           m_fRotation,
                                           m_v2Origin,
                                           m_fScale,
                                           m_seEffects, 0);

            gs.Engine.SpriteBatch.End();

            // Set back certain render states that are changed by the SpriteBatch
            // so they don't interfere with any 3D rendering we may do.
            ResetRenderStates();

        } // end void C2D_Sprite::Draw(GameScreen)

        public void DrawOffset(Vector2 vOffset)
        {
            ParentGameScreen.Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                                            SpriteSortMode.Deferred,
                                            SaveStateMode.None);

            ParentGameScreen.Engine.SpriteBatch.Draw(m_t2dSpriteTexture,
                                           m_v2Position + vOffset,
                                           m_rectSource,
                                           m_Color,
                                           m_fRotation,
                                           m_v2Origin,
                                           m_fScale,
                                           m_seEffects, 0);

            ParentGameScreen.Engine.SpriteBatch.End();

            // Set back certain render states that are changed by the SpriteBatch
            // so they don't interfere with any 3D rendering we may do.
            ResetRenderStates();

        } // end void C2D_Sprite::DrawOffset(Vector2)

        public void DrawOffset(Vector2 vOffset, GameScreen gs)
        {
            gs.Engine.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                                            SpriteSortMode.Deferred,
                                            SaveStateMode.None);

            gs.Engine.SpriteBatch.Draw(m_t2dSpriteTexture,
                                           m_v2Position + vOffset,
                                           m_rectSource,
                                           m_Color,
                                           m_fRotation,
                                           m_v2Origin,
                                           m_fScale,
                                           m_seEffects, 0);

            gs.Engine.SpriteBatch.End();

            // Set back certain render states that are changed by the SpriteBatch
            // so they don't interfere with any 3D rendering we may do.
            ResetRenderStates();

        } // end void C2D_Sprite::DrawOffset(Vector2, GameScreen)



        // DEBUG METHODS
        // ------------------------------------------------------------------------------------------------------------------------

#if (DEBUG)
        // put all debug methods in here...
#endif


        // PROPERTIES
        // ------------------------------------------------------------------------------------------------------------------------

        public Color Color
        {
            get
            {
                return m_Color;
            }
            set
            {
                m_Color = value;
            }
        } // end property Color

        public int Height
        {
            get
            {
                return m_rectSource.Height;
            }
        } // end property Height

        public Vector2 Origin
        {
            get
            {
                return m_v2Origin;
            }
            set
            {
                m_v2Origin = value;
            }
        } // end property Origin

        public Vector2 Position
        {
            get
            {
                return m_v2Position;
            }
            set
            {
                m_v2Position = value;
            }

        } // end property Position

        // Note that the value of the Rotation property is in radians, not degrees.
        public float Rotation
        {
            get
            {
                return m_fRotation;
            }
            set
            {
                m_fRotation = value;
            }
        } // end property Rotation

        public float Scale
        {
            get
            {
                return m_fScale;
            }
            set
            {
                m_fScale = value;
            }
        } // end property Scale

        // "The SourceRectangle determines the area of the original texture that will be sampled and drawn onto the screen.
        // This is useful for drawing spritesheets, which place numerous sprites in the same image, to be cut out later by
        // the graphics card. Using a sprite sheet provides a performance boost as the graphics card doesn’t have to
        // constantly load different textures into memory." - This quote is from the Sprite Effects section of the
        // Game Engine tutorial series V2.0.
        public Rectangle SourceRectangle
        {
            get
            {
                return m_rectSource;
            }
            set
            {
                m_rectSource = value;
            }
        } // end property SourceRectangle

        public SpriteEffects Effects
        {
            get
            {
                return m_seEffects;
            }
            set
            {
                m_seEffects = value;
            }
        } // end property Effects

        public Texture2D SpriteTexture
        {
            get
            {
                return m_t2dSpriteTexture;
            }
            set
            {
                if (value != null)
                    m_t2dSpriteTexture = value;
            }
        } // end property SpriteTexture

        public int Width
        {
            get
            {
                return m_rectSource.Width;
            }
        } // end property Width

        public float X
        {
            get
            {
                return m_v2Position.X;
            }
            set
            {
                m_v2Position.X = value;
            }
        } // end property X

        public float Y
        {
            get
            {
                return m_v2Position.Y;
            }
            set
            {
                m_v2Position.Y = value;
            }
        } // end property Y


        // EVENTS
        // ------------------------------------------------------------------------------------------------------------------------


    } // end class C2D_Sprite
}
